package com.eastfair.pay.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.eastfair.auth.api.UserAccountServiceFeign;
import com.eastfair.auth.dto.UserAccountDto;
import com.eastfair.auth.vo.UserAccountVo;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.common.dto.JYMainnoResultDTO;
import com.eastfair.common.dto.JYPaymentCollectRecordDTO;
import com.eastfair.common.dto.OrderPaymentPlan;
import com.eastfair.common.req.JYReq;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.pay.api.FinanceFeign;
import com.eastfair.pay.dao.CollectRecordMapper;
import com.eastfair.pay.dto.CollectDTO;
import com.eastfair.pay.dto.OrdinaryCollectDTO;
import com.eastfair.pay.dto.UnCollectDTO;
import com.eastfair.pay.entity.CollectRecord;
import com.eastfair.pay.entity.Contract;
import com.eastfair.pay.entity.JyLog;
import com.eastfair.pay.entity.PaymentPlan;
import com.eastfair.pay.entity.PaymentRecord;
import com.eastfair.pay.entity.TransactionOrder;
import com.eastfair.pay.enumeration.TransactionOrderOrderStatusEnum;
import com.eastfair.pay.enums.CollectStateEnum;
import com.eastfair.pay.enums.CollectTypeEnum;
import com.eastfair.pay.enums.OrderStateEnum;
import com.eastfair.pay.enums.PayChannelEnum;
import com.eastfair.pay.enums.PayStateEnum;
import com.eastfair.pay.enums.PayTypeEnum;
import com.eastfair.pay.exceptioncode.PayExceptionCode;
import com.eastfair.pay.service.CollectRecordService;
import com.eastfair.pay.service.ContractService;
import com.eastfair.pay.service.JyLogService;
import com.eastfair.pay.service.JyService;
import com.eastfair.pay.service.PaymentPlanService;
import com.eastfair.pay.service.PaymentRecordService;
import com.eastfair.pay.service.TransactionOrderService;
import com.eastfair.pay.vo.CollectPageDetailVO;
import com.eastfair.pay.vo.CollectRecordVO;
import com.eastfair.pay.vo.PaymentPlanVO;
import com.eastfair.venuebooking.api.ContractManageFeign;
import com.eastfair.venuebooking.dto.ContractManageDTO;
import io.seata.common.util.CollectionUtils;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 认款记录
 * </p>
 *
 * @author clm
 * @date 2022-06-08
 */
@Slf4j
@Service
public class CollectRecordServiceImpl extends SuperServiceImpl<CollectRecordMapper, CollectRecord> implements CollectRecordService {

    @Autowired
    private PaymentPlanService paymentPlanService;
    @Autowired
    private PaymentRecordService paymentRecordService;
    @Autowired
    private CollectRecordMapper collectRecordMapper;
    @Autowired
    private UserAccountServiceFeign userAccountServiceFeign;
    @Autowired
    private ContractService contractService;
    @Autowired
    private ContractManageFeign contractManageFeign;
    @Resource
    private FinanceFeign financeService;
    @Resource
    private TransactionOrderService transactionOrderService;

    @Resource
    private JyService jyService;

    @Resource
    private JyLogService jyLogService;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<CollectRecord> modelList) {
        modelList.stream().forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }

    /**
     * 处理新增相关处理
     *
     * @param model 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerSave(CollectRecord model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        model.setTenantId(ContextUtil.getTenantId());
        return R.successDef();
    }

    @Override
    public List<CollectRecord> queryByPaymentRecordId(@NonNull Long paymentRecordId) {
        LambdaQueryWrapper<CollectRecord> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(CollectRecord::getPaymentRecordId, paymentRecordId);
        List<CollectRecord> collectRecords = baseMapper.selectList(lambdaQueryWrapper);
        return collectRecords;
    }

    /**
     * 通过合同获取认领记录
     *
     * @param contractId
     * @return
     */
    @Override
    public List<CollectRecord> queryCollectRecordList(Long contractId) {
        LambdaQueryWrapper<CollectRecord> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(CollectRecord::getBusinessId, contractId);
        return baseMapper.selectList(lambdaQueryWrapper);
    }

    /**
     * 认领
     *
     * @param collectDTO
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void collect(CollectDTO collectDTO) {

        /**
         * 1、保存认领记录
         * 2、更新付款计划状态
         * 3、更新付款记录状态
         * */

        String collectType = collectDTO.getCollectType();
        Contract contract = contractService.getByBusinessId(collectDTO.getBusinessId());
        log.info("查询合同成功,contract={}", contract);
        if (contract == null) {
            throw new BizException("合同不存在,businessId=" + collectDTO.getBusinessId());
        }
        //该类型未认领金额
        BigDecimal unCollectForType = getUnCollectForType(collectType, collectDTO.getBusinessId());

        //判断认款金额与付款计划金额是否一致
        PaymentPlan paymentPlan = paymentPlanService.getById(collectDTO.getPaymentPlanId());
        log.info("查询合同付款计划成功,paymentPlan={}", paymentPlan);
        if (paymentPlan == null) {
            throw new BizException("合同付款计划不存在,paymentPlanId=" + collectDTO.getPaymentPlanId());
        }

        if (BigDecimal.ZERO.compareTo(unCollectForType.subtract(collectDTO.getCollectAmount())) != 0) {
            throw BizException.wrap(PayExceptionCode.PAYMENT_PLAN_EXCEED_COLLECT);
        }

        //判断认款金额超出付款记录金额
        PaymentRecord paymentRecord = paymentRecordService.getById(collectDTO.getPaymentRecordId());
        log.info("查询付款记录成功,paymentRecord={}", paymentRecord);
        if (paymentRecord == null) {
            throw new BizException("付款记录不存在,paymentRecordId=" + collectDTO.getPaymentRecordId());
        }
        if (paymentRecord.getPayAmount().subtract(paymentRecord.getCollectAmount() == null ? new BigDecimal(0) : paymentRecord.getCollectAmount()).compareTo(paymentRecord.getCollectAmount() == null ? new BigDecimal(0) : collectDTO.getCollectAmount()) == -1) {
            throw BizException.wrap(PayExceptionCode.PAYMENT_RECORD_EXCEED_COLLECT);
        }

        //认领记录同步荆艺
        TransactionOrder transactionOrder = transactionOrderService.getByOrderNum(contract.getContractNumber());
        log.info("查询交易订单成功,transactionOrder={}", transactionOrder);
        if (transactionOrder == null) {
            throw new BizException("交易订单不存在,OrderNum=" + contract.getContractNumber());
        }
        //构建荆艺认款记录对象
        JYReq<JYPaymentCollectRecordDTO> jyReqestDTO = jyService.buildCollectToJy(paymentRecord, transactionOrder, collectDTO.getCollectAmount());
        JyLog jyLog = new JyLog()
                .setMethodName("同步认款记录")
                .setTableName(transactionOrder.getClass().getName())
                .setLinkId(String.valueOf(transactionOrder.getOrderNum()))
                .setRequestParameter(JSON.toJSONString(jyReqestDTO));
        log.info("同步认款记录入参，req={}", jyReqestDTO);
        R<List<JYMainnoResultDTO>> result = financeService.sync(jyReqestDTO);
        jyLog.setResponseResults(JSON.toJSONString(result));
        log.info("同步认款记录出参，result={}", result);
        if (result != null && result.getIsSuccess()) {
            jyLog.setIsSuccess(BusinessConstant.ENABLE_YES);
            if (CollectionUtils.isNotEmpty(result.getData())) {
                //保存认款记录
                CollectRecord collectRecord = BeanUtil.copyProperties(collectDTO, CollectRecord.class);
                collectRecord.setPayType(paymentRecord.getPayType());
                collectRecord.setBankAccountName(paymentRecord.getBankAccountName());
                collectRecord.setBusinessCode(collectDTO.getBusinessCode());
                collectRecord.setBusinessId(collectDTO.getBusinessId());
                collectRecord.setMainno(result.getData().get(0).getMainno());
                //保存认领记录
                save(collectRecord);
                log.info("保存认款记录成功,collectRecord={}", collectRecord);
                //更新付款计划
                paymentPlan.setPayedAmount((paymentPlan.getPayedAmount() == null ? new BigDecimal(0) : paymentPlan.getPayedAmount()).add(collectDTO.getCollectAmount()));
                if (paymentPlan.getPayedAmount().compareTo(paymentPlan.getPlanPayAmount()) == 0) {
                    paymentPlan.setPayState(PayStateEnum.PAYED.getCode());
                } else {
                    paymentPlan.setPayState(PayStateEnum.PART_PAY.getCode());
                }
                paymentPlanService.updateById(paymentPlan);
                log.info("更新付款计划成功,paymentPlan={}", paymentPlan);
                //更新付款记录
                paymentRecord.setCollectAmount((paymentRecord.getCollectAmount() == null ? new BigDecimal(0) : paymentRecord.getCollectAmount()).add(collectDTO.getCollectAmount()));
                if (paymentRecord.getCollectAmount().compareTo(paymentRecord.getPayAmount()) == 0) {
                    paymentRecord.setCollectState(CollectStateEnum.IS_COLLECTED.getCode());
                } else {
                    paymentRecord.setCollectState(CollectStateEnum.PART_COLLECTED.getCode());
                }
                paymentRecordService.updateById(paymentRecord);
                log.info("更新付款记录成功,paymentRecord={}", paymentRecord);
                //更新合同付款状态及回款金额
                ContractManageDTO contractManageDTO = putContractManageDTO(collectDTO.getBusinessId());

                contract.setContractReturndAmount(contractManageDTO.getContractReturndAmount());
                contractService.updateById(contract);
                log.info("更新合同成功,contract={}", contract);
                contractManageFeign.updateForCollect(contractManageDTO);
                // 更新交易订单的状态
                if (PayStateEnum.PAYED.equals(PayStateEnum.valueOf(contractManageDTO.getContractPayState()))) {
                    transactionOrder.setOrderStatus(TransactionOrderOrderStatusEnum.PAYED);
                    transactionOrder.setState(OrderStateEnum.COMPLETED.getCode());
                } else {
                    transactionOrder.setOrderStatus(TransactionOrderOrderStatusEnum.PARTPAY);
                }

                // 更新订单付款计划
                List<PaymentPlan> paymentPlans = paymentPlanService.lambdaQuery().eq(PaymentPlan::getBusinessId, collectDTO.getBusinessId()).orderByAsc(PaymentPlan::getPlanPayTime).list();
                if (CollectionUtils.isNotEmpty(paymentPlans)) {
                    List<OrderPaymentPlan> orderPaymentPlans = paymentPlans.stream().map(p -> {
                        OrderPaymentPlan orderPlan = new OrderPaymentPlan();
                        orderPlan.setFkje(p.getPlanPayAmount());
                        orderPlan.setFkrq(DateUtil.format(p.getPlanPayTime(), "yyyy-MM-dd HH:mm:ss"));
                        orderPlan.setPayState(p.getPayState());
                        orderPlan.setStagesTag(p.getStagesTag());
                        List<CollectRecord> records = lambdaQuery().eq(CollectRecord::getBusinessCode, collectDTO.getBusinessCode()).list();
                        if (CollectionUtils.isNotEmpty(records)) {
                            PaymentRecord payment = paymentRecordService.getById(records.get(0).getPaymentRecordId());
                            orderPlan.setPayOrderNo(payment.getMainno());
                        }
                        return orderPlan;
                    }).collect(Collectors.toList());
                    transactionOrder.setPaymentPlan(JSON.toJSONString(orderPaymentPlans));
                }
                transactionOrder.setPayType(PayTypeEnum.TRANSFER_ACCOUNT.getCode());
                transactionOrder.setPayChannel(PayChannelEnum.CORPORATE_TRANSGER.getCode());
                transactionOrderService.updateById(transactionOrder);
                log.info("更新交易订单成功,transactionOrder={}", transactionOrder);
                jyLogService.save(jyLog);
                return;
            }
        }
        jyLogService.save(jyLog);
        throw new BizException("财务认款失败");

    }

    private ContractManageDTO putContractManageDTO(Long businessId) {
        ContractManageDTO contractManageDTO = new ContractManageDTO();
        contractManageDTO.setId(businessId);
        Contract contract = contractService.getByBusinessId(businessId);
        BigDecimal totalReturnAmount = baseMapper.getTotalReturnAmount(businessId);
        int flag = (totalReturnAmount == null ? new BigDecimal(0) : totalReturnAmount).compareTo(contract.getContractAmount());
        contractManageDTO.setContractPayState(flag == 0 ? PayStateEnum.PAYED.getCode() : PayStateEnum.PART_PAY.getCode());
        contractManageDTO.setContractReturndAmount(totalReturnAmount == null ? new BigDecimal(0) : totalReturnAmount);
        return contractManageDTO;
    }


    /**
     * 取消认领（合同）
     *
     * @param unCollectDTO
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void unCollect(UnCollectDTO unCollectDTO) {

        /**
         * 1、更新付款计划认领状态
         * 2、更新付款记录认领状态
         * 3、删除认款记录
         */
        CollectRecord collectRecord = collectRecordMapper.selectById(unCollectDTO.getCollectRecordId());
        log.info("查询认款记录成功,collectRecord={}", collectRecord);
        if (collectRecord == null) {
            throw new BizException("认款记录不存在,businessId=" + unCollectDTO.getCollectRecordId());
        }
        Contract contract = contractService.getByBusinessId(collectRecord.getBusinessId());
        log.info("查询合同成功,contract={}", contract);
        if (contract == null) {
            throw new BizException("合同不存在,businessId=" + collectRecord.getBusinessId());
        }
        if (contract.getInvoicedAmount().compareTo(new BigDecimal(0)) != 0) {
            BizException.wrap(PayExceptionCode.ALREADY_INVOICED);
        }
        PaymentPlan paymentPlan = paymentPlanService.getById(collectRecord.getPaymentPlanId());
        log.info("查询合同付款计划成功,paymentPlan={}", paymentPlan);
        if (paymentPlan == null) {
            throw new BizException("合同付款计划不存在,paymentPlanId=" + collectRecord.getPaymentPlanId());
        }
        if (paymentPlan.getPayedAmount().compareTo(collectRecord.getCollectAmount()) <= 0) {
            paymentPlan.setPayState(PayStateEnum.UN_PAY.getCode());
        } else {
            paymentPlan.setPayState(PayStateEnum.PART_PAY.getCode());
        }

        PaymentRecord paymentRecord = paymentRecordService.getById(collectRecord.getPaymentRecordId());
        log.info("查询付款记录成功,paymentRecord={}", paymentRecord);
        if (paymentRecord == null) {
            throw new BizException("付款记录不存在,paymentRecordId=" + collectRecord.getPaymentRecordId());
        }
        // 查询订单
        TransactionOrder transactionOrder = transactionOrderService.getByOrderNum(collectRecord.getBusinessCode());
        log.info("查询订单记录成功,transactionOrder={}", transactionOrder);
        if (transactionOrder == null) {
            throw new BizException("订单记录不存在,businessCode=" + collectRecord.getBusinessCode());
        }

        //调荆艺接口取消认领
        JYReq<JYPaymentCollectRecordDTO> jyReqestDTO = jyService.buildCancelCollectToJy(paymentRecord, collectRecord);
        JyLog jyLog = new JyLog()
                .setMethodName("同步取消认领记录")
                .setTableName(collectRecord.getClass().getName())
                .setLinkId(String.valueOf(collectRecord.getBusinessId()))
                .setRequestParameter(JSON.toJSONString(jyReqestDTO));
        log.info("取消认款入参，req={}", jyReqestDTO);
        R<List<JYMainnoResultDTO>> result = financeService.sync(jyReqestDTO);
        log.info("取消认款出参，result={}", result);
        jyLog.setResponseResults(JSON.toJSONString(result));
        if (result != null && result.getIsSuccess()) {
            jyLog.setIsSuccess(BusinessConstant.ENABLE_YES);
            if (CollectionUtils.isNotEmpty(result.getData())) {
                paymentPlan.setPayedAmount(paymentPlan.getPayedAmount().subtract(collectRecord.getCollectAmount()));
                paymentPlanService.updateById(paymentPlan);
                log.info("更新付款计划成功,paymentPlan={}", paymentPlan);
                if (paymentRecord.getCollectAmount().compareTo(collectRecord.getCollectAmount()) <= 0) {
                    paymentRecord.setCollectState(CollectStateEnum.UN_COLLECTED.getCode());
                } else {
                    paymentRecord.setCollectState(CollectStateEnum.PART_COLLECTED.getCode());
                }
                paymentRecord.setCollectAmount(paymentRecord.getCollectAmount().subtract(collectRecord.getCollectAmount()));
                paymentRecordService.updateById(paymentRecord);
                log.info("更新付款记录成功,paymentRecord={}", paymentRecord);
                // 保存订单
                // 判断订单状态
                if (transactionOrder.getOrderAmount().compareTo(collectRecord.getCollectAmount()) <= 0) {
                    // 订单认款金额全部取消
                    // 修改订单记录状态为未付款
                    transactionOrder.setOrderStatus(TransactionOrderOrderStatusEnum.UNPAY);
                } else {
                    // 订单认款金额部分取消
                    // 修改订单记录状态为部分付款
                    transactionOrder.setOrderStatus(TransactionOrderOrderStatusEnum.PARTPAY);
                }
                transactionOrder.setState(OrderStateEnum.IN_PROGRESS.getCode());
                transactionOrderService.updateById(transactionOrder);
                collectRecordMapper.deleteById(unCollectDTO.getCollectRecordId());
                log.info("删除认款记录成功");
                processContract(contract, collectRecord);
                return;
            }
        }
        jyLogService.save(jyLog);
        throw new BizException("财务取消认款失败");

    }

    /**
     * 取消认领（通用）
     *
     * @param unCollectDTO
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void commonUncollect(UnCollectDTO unCollectDTO) {

        CollectRecord collectRecord = collectRecordMapper.selectById(unCollectDTO.getCollectRecordId());
        log.info("查询认款记录成功,collectRecord={}", collectRecord);
        if (collectRecord == null) {
            throw new BizException("认款记录不存在,collectRecordId=" + unCollectDTO.getCollectRecordId());
        }
        PaymentRecord paymentRecord = paymentRecordService.getById(collectRecord.getPaymentRecordId());
        log.info("查询付款记录成功,paymentRecord={}", paymentRecord);
        if (paymentRecord == null) {
            throw new BizException("付款记录不存在,paymentRecordId=" + collectRecord.getPaymentRecordId());
        }
        // 查询订单
        TransactionOrder transactionOrder = transactionOrderService.getByOrderNum(collectRecord.getBusinessCode());
        log.info("查询订单记录成功,transactionOrder={}", transactionOrder);
        if (transactionOrder == null) {
            throw new BizException("订单记录不存在,businessCode=" + collectRecord.getBusinessCode());
        }
        // 判断认领进入是否超出订单总金额
        if (collectRecord.getCollectAmount().compareTo(transactionOrder.getOrderAmount()) == 1) {
            throw new BizException("取消认款金额大于订单总金额,collectAmount=" + collectRecord.getCollectAmount());
        }

        //调荆艺接口取消认领
        JYReq<JYPaymentCollectRecordDTO> jyReqestDTO = jyService.buildCancelCollectToJy(paymentRecord, collectRecord);
        log.info("取消认款入参，req={}", jyReqestDTO);
        R<List<JYMainnoResultDTO>> result = financeService.sync(jyReqestDTO);
        log.info("取消认款出参，result={}", result);
        if (result != null && result.getIsSuccess()) {
            if (CollectionUtils.isNotEmpty(result.getData())) {
                if (paymentRecord.getCollectAmount().compareTo(collectRecord.getCollectAmount()) <= 0) {
                    // 修改付款记录状态为未认领
                    paymentRecord.setCollectState(CollectStateEnum.UN_COLLECTED.getCode());
                } else {
                    // 修改付款记录状态为部分认领
                    paymentRecord.setCollectState(CollectStateEnum.PART_COLLECTED.getCode());
                }
                //保存认款记录
                paymentRecord.setCollectAmount(paymentRecord.getCollectAmount().subtract(collectRecord.getCollectAmount()));
                paymentRecordService.updateById(paymentRecord);
                log.info("更新付款记录成功,paymentRecord={}", paymentRecord);
                // 保存订单
                // 判断订单状态
                if (transactionOrder.getOrderAmount().compareTo(collectRecord.getCollectAmount()) <= 0) {
                    // 订单认款金额全部取消
                    // 修改订单记录状态为未付款
                    transactionOrder.setOrderStatus(TransactionOrderOrderStatusEnum.UNPAY);
                } else {
                    // 订单认款金额部分取消
                    // 修改订单记录状态为部分付款
                    transactionOrder.setOrderStatus(TransactionOrderOrderStatusEnum.PARTPAY);
                }
                transactionOrder.setState(OrderStateEnum.IN_PROGRESS.getCode());
                transactionOrderService.updateById(transactionOrder);
                log.info("更新订单记录成功,transactionOrder={}", transactionOrder);
                collectRecordMapper.deleteById(unCollectDTO.getCollectRecordId());
                log.info("删除认款记录成功");
                return;
            }
        }
        throw new BizException("财务取消认款失败");

    }

    private void processContract(Contract contract, CollectRecord collectRecord) {

        contract.setContractReturndAmount(contract.getContractReturndAmount().subtract(collectRecord.getCollectAmount()));
        contractService.updateById(contract);

        ContractManageDTO contractManageDTO = new ContractManageDTO();
        contractManageDTO.setId(collectRecord.getBusinessId());
        //只要有取消认款合同的状态就是部分付款
        contractManageDTO.setContractPayState(PayStateEnum.PART_PAY.getCode());
        contractManageDTO.setContractReturndAmount(contract.getContractReturndAmount());
        //如果付款金额为0则未付款
        if (contractManageDTO.getContractReturndAmount().compareTo(new BigDecimal(0)) != 1) {
            contractManageDTO.setContractPayState(PayStateEnum.UN_PAY.getCode());
        }
        contractManageFeign.updateForCollect(contractManageDTO);
    }

    /**
     * 通过合同获取认领页面详情
     *
     * @param businessId
     * @return
     */
    @Override
    public CollectPageDetailVO getCollectPageDetail(Long businessId) {

        CollectPageDetailVO collectPageDetailVO = new CollectPageDetailVO();

        //组装付款计划
        List<PaymentPlan> paymentPlans = paymentPlanService.queryByBusinessId(businessId);
        List<PaymentPlanVO> paymentPlanVOList = ConvertUtil.convertList(paymentPlans, PaymentPlanVO.class);
        for (PaymentPlanVO paymentPlanVO : paymentPlanVOList) {
            paymentPlanVO.setUnpayAmount(paymentPlanVO.getPlanPayAmount().subtract(paymentPlanVO.getPayedAmount()));
            paymentPlanVO.setStagesTagStr("第" + paymentPlanVO.getStagesTag() + "期" + "(" + paymentPlanVOList.size() + "期)");
        }
        collectPageDetailVO.setPaymentPlanVOS(paymentPlanVOList);

        //组装款项未认领金额
        Contract contract = contractService.getByBusinessId(businessId);
        List<CollectRecord> collectRecordList = queryCollectRecordList(businessId);
        Map<String, List<CollectRecord>> collectTypeMap = CollectionUtil.isEmpty(collectRecordList) ? new HashMap<>(8) : collectRecordList.stream().collect(Collectors.groupingBy(CollectRecord::getCollectType));
        List<CollectPageDetailVO.UnCollectAmount> unCollectAmountList = new ArrayList<>();


        CollectPageDetailVO.UnCollectAmount unCollectAmountForES = new CollectPageDetailVO.UnCollectAmount();
        unCollectAmountForES.setCollectType(CollectTypeEnum.EXHIBITION_SERVICE.getCode());
        unCollectAmountForES.setUnCollectAmount(getUnCollectAmount(CollectTypeEnum.EXHIBITION_SERVICE.getCode(), contract, collectTypeMap.get(CollectTypeEnum.EXHIBITION_SERVICE.getCode())));

        CollectPageDetailVO.UnCollectAmount unCollectAmountSEB = new CollectPageDetailVO.UnCollectAmount();
        unCollectAmountSEB.setCollectType(CollectTypeEnum.SERVICE_BOND.getCode());
        unCollectAmountSEB.setUnCollectAmount(getUnCollectAmount(CollectTypeEnum.SERVICE_BOND.getCode(), contract, collectTypeMap.get(CollectTypeEnum.SERVICE_BOND.getCode())));

        CollectPageDetailVO.UnCollectAmount unCollectAmountSPB = new CollectPageDetailVO.UnCollectAmount();
        unCollectAmountSPB.setCollectType(CollectTypeEnum.SPACE_BOND.getCode());
        unCollectAmountSPB.setUnCollectAmount(getUnCollectAmount(CollectTypeEnum.SPACE_BOND.getCode(), contract, collectTypeMap.get(CollectTypeEnum.SPACE_BOND.getCode())));

        unCollectAmountList.add(unCollectAmountForES);
        unCollectAmountList.add(unCollectAmountSEB);
        unCollectAmountList.add(unCollectAmountSPB);

        collectPageDetailVO.setUnCollectAmountList(unCollectAmountList);
        return collectPageDetailVO;
    }

    private BigDecimal getUnCollectAmount(String collectType, Contract contract, List<CollectRecord> collectRecords) {

        BigDecimal collectAmount = new BigDecimal(0);
        if (!CollectionUtil.isEmpty(collectRecords)) {
            for (CollectRecord collectRecord : collectRecords) {
                collectAmount = collectAmount.add(collectRecord.getCollectAmount());
            }
        }

        if (CollectTypeEnum.EXHIBITION_SERVICE.getCode().equals(collectType)) {
            return contract.getContractAmount().subtract(contract.getServiceBond()).subtract(contract.getSpaceBond()).subtract(collectAmount);
        } else if (CollectTypeEnum.SERVICE_BOND.getCode().equals(collectType)) {
            return contract.getServiceBond().subtract(collectAmount);
        } else if (CollectTypeEnum.SPACE_BOND.getCode().equals(collectType)) {
            return contract.getSpaceBond().subtract(collectAmount);
        }

        return new BigDecimal(0);
    }

    private BigDecimal getUnCollectForType(String collectType, Long businessId) {
        Contract contract = contractService.getByBusinessId(businessId);
        //获取合同当前类型的认款总额
        BigDecimal collectForType = collectRecordMapper.getUnCollectForType(collectType, businessId);
        BigDecimal typeAmount = getTypeAmount(collectType, contract);
        return typeAmount.subtract(collectForType);
    }

    private BigDecimal getTypeAmount(String collectType, Contract contract) {
        BigDecimal typeAmount;
        if (CollectTypeEnum.EXHIBITION_SERVICE.getCode().equals(collectType)) {
            typeAmount = contract.getContractAmount().subtract(contract.getServiceBond()).subtract(contract.getSpaceBond());
        } else if (CollectTypeEnum.SERVICE_BOND.getCode().equals(collectType)) {
            typeAmount = contract.getServiceBond();
        } else if (CollectTypeEnum.SPACE_BOND.getCode().equals(collectType)) {
            typeAmount = contract.getSpaceBond();
        } else {
            throw BizException.wrap(PayExceptionCode.UNKNOWEN_COLLECT_TYPE);
        }
        return typeAmount;
    }

    /**
     * 获取付款计划的认领记录
     *
     * @param paymentPlanId
     * @return
     */

    @Override
    public List<CollectRecordVO> queryCollectByPlanId(Long paymentPlanId) {
        List<CollectRecordVO> collectRecordVOS = collectRecordMapper.queryCollectByPlanId(paymentPlanId);
        if (CollectionUtil.isEmpty(collectRecordVOS)) {
            return new ArrayList<>();
        }
        //填充用户名
        fillUser(collectRecordVOS);
        return collectRecordVOS;
    }

    /**
     * 获取付款记录的认领记录
     *
     * @param recordId
     * @return
     */
    @Override
    public List<CollectRecordVO> queryCollectByRecordId(Long recordId) {
        List<CollectRecordVO> collectRecordVOS = collectRecordMapper.queryCollectByRecordId(recordId);
        //填充用户名
        fillUser(collectRecordVOS);
        return collectRecordVOS;
    }

    @Override
    public CollectRecord getRecordByOrderNum(String orderNum) {
        LambdaQueryWrapper<CollectRecord> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(CollectRecord::getBusinessCode, orderNum);
        lambdaQueryWrapper.eq(CollectRecord::getIsDeleted, BusinessConstant.DELETE_NO);
        return baseMapper.selectOne(lambdaQueryWrapper);
    }

    @Override
    public List<CollectRecord> getRecordListByOrderNum(String orderNum) {
        LambdaQueryWrapper<CollectRecord> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(CollectRecord::getBusinessCode, orderNum);
        lambdaQueryWrapper.eq(CollectRecord::getIsDeleted, BusinessConstant.DELETE_NO);
        return baseMapper.selectList(lambdaQueryWrapper);
    }

    private void fillUser(List<CollectRecordVO> collectRecordVOS) {
        if (CollectionUtil.isEmpty(collectRecordVOS)) {
            return;
        }
        List<Long> userIds = collectRecordVOS.stream().map(CollectRecordVO::getCollectUserId).collect(Collectors.toList());
        UserAccountDto userAccountDto = new UserAccountDto();
        userAccountDto.setUserIds(userIds);
        R<List<UserAccountVo>> listR = userAccountServiceFeign.querySimpleByIds(userAccountDto);
        List<UserAccountVo> data = listR.getData();
        Map<Long, String> userIdNameMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(data)) {
            userIdNameMap = data.stream().collect(Collectors.toMap(UserAccountVo::getId, UserAccountVo::getRealName));
        }
        for (CollectRecordVO collectRecordVO : collectRecordVOS) {
            collectRecordVO.setCollectUser(userIdNameMap.get(collectRecordVO.getCollectUserId()));
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void ordinaryCollect(OrdinaryCollectDTO collectDTO) {
        //判断认款金额超出付款记录金额
        PaymentRecord paymentRecord = paymentRecordService.getById(collectDTO.getPaymentRecordId());
        log.info("查询付款记录成功,paymentRecord={}", paymentRecord);
        if (paymentRecord == null) {
            throw new BizException("付款记录不存在,paymentRecordId=" + collectDTO.getPaymentRecordId());
        }
        if (paymentRecord.getPayAmount().subtract(paymentRecord.getCollectAmount() == null ? new BigDecimal(0) : paymentRecord.getCollectAmount()).compareTo(paymentRecord.getCollectAmount() == null ? new BigDecimal(0) : collectDTO.getCollectAmount()) == -1) {
            throw BizException.wrap(PayExceptionCode.PAYMENT_RECORD_EXCEED_COLLECT);
        }
        //认领记录同步荆艺
        TransactionOrder transactionOrder = transactionOrderService.getByOrderNum(collectDTO.getOrderNum());
        log.info("查询交易订单成功,transactionOrder={}", transactionOrder);
        if (transactionOrder == null) {
            throw new BizException("交易订单不存在,OrderNum=" + collectDTO.getOrderNum());
        }
        // 判断认款金额和订单金额是否一致
        if (BigDecimal.ZERO.compareTo(transactionOrder.getOrderAmount().subtract(collectDTO.getCollectAmount())) != 0) {
            throw BizException.wrap(PayExceptionCode.ORDER_EXCEED_COLLECT);
        }
        //构建荆艺认款记录对象
        JYReq<JYPaymentCollectRecordDTO> jyReqestDTO = jyService.buildCollectToJy(paymentRecord, transactionOrder, collectDTO.getCollectAmount());
        JyLog jyLog = new JyLog()
                .setMethodName("同步认款记录")
                .setTableName(transactionOrder.getClass().getName())
                .setLinkId(String.valueOf(transactionOrder.getOrderNum()))
                .setRequestParameter(JSON.toJSONString(jyReqestDTO));
        log.info("同步认款记录入参，req={}", jyReqestDTO);
        R<List<JYMainnoResultDTO>> result = financeService.sync(jyReqestDTO);
        jyLog.setResponseResults(JSON.toJSONString(result));
        log.info("同步认款记录出参，result={}", result);
        if (result != null && result.getIsSuccess()) {
            jyLog.setIsSuccess(BusinessConstant.ENABLE_YES);
            if (CollectionUtils.isNotEmpty(result.getData())) {
                //保存认款记录
                CollectRecord collectRecord = BeanUtil.copyProperties(collectDTO, CollectRecord.class);
                collectRecord.setPayType(paymentRecord.getPayType());
                collectRecord.setBankAccountName(paymentRecord.getBankAccountName());
                collectRecord.setBusinessCode(transactionOrder.getOrderNum());
                collectRecord.setMainno(result.getData().get(0).getMainno());
                //保存认领记录
                save(collectRecord);
                log.info("保存认款记录成功,collectRecord={}", collectRecord);
                //更新付款记录
                paymentRecord.setCollectAmount((paymentRecord.getCollectAmount() == null ? new BigDecimal(0) : paymentRecord.getCollectAmount()).add(collectDTO.getCollectAmount()));
                if (paymentRecord.getCollectAmount().compareTo(paymentRecord.getPayAmount()) == 0) {
                    paymentRecord.setCollectState(CollectStateEnum.IS_COLLECTED.getCode());
                } else {
                    paymentRecord.setCollectState(CollectStateEnum.PART_COLLECTED.getCode());
                }
                paymentRecordService.updateById(paymentRecord);
                log.info("更新付款记录成功,paymentRecord={}", paymentRecord);
                // 更新交易订单的状态
                BigDecimal sumAmount = calSumAmountByOrderNum(transactionOrder.getOrderNum());
                if (transactionOrder.getOrderAmount().compareTo(sumAmount) < 0) {
                    transactionOrder.setOrderStatus(TransactionOrderOrderStatusEnum.PARTPAY);
                } else {
                    transactionOrder.setOrderStatus(TransactionOrderOrderStatusEnum.PAYED);
                    transactionOrder.setState(OrderStateEnum.COMPLETED.getCode());
                }
                transactionOrder.setPayType(PayTypeEnum.TRANSFER_ACCOUNT.getCode());
                transactionOrder.setPayChannel(PayChannelEnum.CORPORATE_TRANSGER.getCode());
                transactionOrder.setPayOrderNo(paymentRecord.getMainno());
                transactionOrderService.updateById(transactionOrder);
                log.info("更新交易订单成功,transactionOrder={}", transactionOrder);
                jyLogService.save(jyLog);
                return;
            }
        }
        jyLogService.save(jyLog);
        throw new BizException("财务认款失败");
    }

    /**
     * 订单计算认款总金额
     *
     * @param orderNum
     * @return
     */
    @Override
    public BigDecimal calSumAmountByOrderNum(String orderNum) {
        List<CollectRecord> recordList = getRecordListByOrderNum(orderNum);
        return recordList.stream().map(CollectRecord::getCollectAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    @Override
    public List<CollectRecordVO> queryCollectRecordByOrderNum(String orderNum) {
        List<CollectRecordVO> collectRecordVOS = baseMapper.getRecordListByOrderNum(orderNum);
        if (CollectionUtil.isEmpty(collectRecordVOS)) {
            return new ArrayList<>();
        }
        //填充用户名
        fillUser(collectRecordVOS);
        return collectRecordVOS;
    }
}
